package com.shchekoldin.server;

import com.sun.jersey.spi.container.servlet.ServletContainer;
import org.mortbay.jetty.Connector;
import org.mortbay.jetty.Handler;
import org.mortbay.jetty.Server;
import org.mortbay.jetty.handler.ResourceHandler;
import org.mortbay.jetty.nio.SelectChannelConnector;
import org.mortbay.jetty.servlet.Context;
import org.mortbay.jetty.servlet.ServletHolder;
import org.mortbay.thread.QueuedThreadPool;

import java.net.URL;

public class JettyServer {

    private static final int THREAD_POOL_MAX_THREADS = 100;

    private static final int CONNECTOR_PORT = 84;

    private static final int CONNECTOR_MAX_IDLE_TIME = 30000;

    private static final String REST_PACKAGE = "com.shchekoldin.server.rest";

    private static final String RESOURCE_PATH = "com/shchekoldin/server/web";

    private Server server;

    // -------------------------------------------------------
    // LOGIC
    // -------------------------------------------------------

    private ServletHolder createJerseyServletHolder() {
        ServletHolder servletHolder = new ServletHolder(ServletContainer.class);

        servletHolder.setInitParameter(
            "com.sun.jersey.config.property.resourceConfigClass",
            "com.sun.jersey.api.core.PackagesResourceConfig"
        );
        servletHolder.setInitParameter("com.sun.jersey.config.property.packages", REST_PACKAGE);
        servletHolder.setInitParameter("com.sun.jersey.api.json.POJOMappingFeature", "true");

        return servletHolder;
    }

    private ResourceHandler createResourceHandler() {
        final URL resourceUrl = this.getClass().getClassLoader().getResource(RESOURCE_PATH);
        final String resourceUrlString = resourceUrl.toExternalForm();

        ResourceHandler resourceHandler = new ResourceHandler();
        resourceHandler.setResourceBase(resourceUrlString);

        return resourceHandler;
    }

    private void initializeServer() {
        server = new Server();

        // Thread pool
        QueuedThreadPool threadPool = new QueuedThreadPool();
        threadPool.setMaxThreads(THREAD_POOL_MAX_THREADS);
        server.setThreadPool(threadPool);

        // NIO connector
        SelectChannelConnector connector = new SelectChannelConnector();
        connector.setPort(CONNECTOR_PORT);
        connector.setMaxIdleTime(CONNECTOR_MAX_IDLE_TIME);
        server.setConnectors(new Connector[]{ connector });

        // Handlers
        Context context = new Context(server, "/", Context.NO_SESSIONS);
        context.addServlet(createJerseyServletHolder(), "/rest/*");

        server.setHandlers(new Handler[]{ createResourceHandler(), context });
    }

    //
    // API
    //

    public JettyServer() {
        initializeServer();
    }

    public void run() throws Exception {
        server.start();
        server.join();
    }

}
